﻿using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace Infrastructure.Persistence.Extensions;

public static class ModelBuilderExtensions
{
    public static void ApplyGlobalFilters<TInterface>(this ModelBuilder modelBuilder, Expression<Func<TInterface, bool>> expression)
    {
        var entities = modelBuilder.Model
            .GetEntityTypes()
            .Where(e => e.ClrType.GetInterface(typeof(TInterface).Name) != null)
            .Select(e => e.ClrType);
        foreach (var entity in entities)
        {
            var newParam = Expression.Parameter(entity);
            var newBody = ReplacingExpressionVisitor.Replace(expression.Parameters.Single(), newParam, expression.Body);
            modelBuilder.Entity(entity).HasQueryFilter(Expression.Lambda(newBody, newParam));
        }
    }

    public static void ApplyGlobalFilters<TSoftDelete, TTenant>(this ModelBuilder modelBuilder,
    Expression<Func<TSoftDelete, bool>> softDeleteExpression,
    Expression<Func<TTenant, bool>> tenantExpression)
    {
        var entities = modelBuilder.Model
            .GetEntityTypes()
            .Where(e => e.ClrType.GetInterface(typeof(TSoftDelete).Name) != null &&
                        e.ClrType.GetInterface(typeof(TTenant).Name) != null)
            .Select(e => e.ClrType);

        foreach (var entity in entities)
        {
            var newParam = Expression.Parameter(entity);

            // Soft Delete 过滤器
            var newSoftDeleteBody = ReplacingExpressionVisitor.Replace(softDeleteExpression.Parameters.Single(), newParam, softDeleteExpression.Body);

            // Tenant 过滤器
            var newTenantBody = ReplacingExpressionVisitor.Replace(tenantExpression.Parameters.Single(), newParam, tenantExpression.Body);

            // 合并 Soft Delete 和 Tenant 过滤器
            var combinedFilter = Expression.AndAlso(newSoftDeleteBody, newTenantBody);

            modelBuilder.Entity(entity).HasQueryFilter(Expression.Lambda(combinedFilter, newParam));
        }
    }
}
